using System;
using System.Diagnostics;
using System.Globalization;

using Atomic.Libraries;
using Atomic.Structures;

namespace Atomic.Structures
{
	[Serializable]
	[DebuggerDisplay("{DebuggerDisplay}")]
	public class Site
	{
		[NonSerialized] int hashCode;

		public Site(Atom atom, Position position)
		{
			Atom = atom;
			Position = position;
		}

		/*public virtual Site Clone(Position position)
		{
			return new Site(Atom, position);
		}*/

		public virtual bool Equals(Site other)
		{
			if (object.ReferenceEquals(other, null))
			{
				return false;
			}

			/*if (other is VaspSite)
			{
				// Special rules here. Implemented in the other class.
				return other.Equals(this);
			}*/

			return EqualityHelper.Equals(this, other, new object[] { Atom, Position }, new object[] { other.Atom, other.Position }, hashCode, other.hashCode);
		}

		public override bool Equals(object other)
		{
			return Equals(other as Site);
		}

		public override int GetHashCode()
		{
			if (hashCode == 0)
			{
				hashCode = EqualityHelper.HashCode(new object[] { Atom, Position });
			}

			return hashCode;
		}

		public static bool operator ==(Site site1, Site site2)
		{
			if (object.ReferenceEquals(site1, null))
			{
				if (object.ReferenceEquals(site2, null))
				{
					return true;
				}

				return false;
			}

			return site1.Equals(site2);
		}

		public static bool operator !=(Site site1, Site site2)
		{
			return !(site1 == site2);
		}

		public Atom Atom
		{
			get;
			private set;
		}

		public Position Position
		{
			get;
			private set;
		}

		private string DebuggerDisplay
		{
			get
			{
				return string.Format(CultureInfo.InvariantCulture, "({0:f4}, {1:f4}, {2:f4}) > ({3:f4}, {4:f4}, {5:f4}) {6}",
					Position.Coordinates.X, Position.Coordinates.Y, Position.Coordinates.Z,
					Position.PhysicalCoordinates.X, Position.PhysicalCoordinates.Y, Position.PhysicalCoordinates.Z, Atom.Symbol);
			}
		}
	}
}
